home *** CD-ROM | disk | FTP | other *** search
/ Aminet 37 / Aminet 37 (2000)(Schatztruhe)[!][Jun 2000].iso / Aminet / comm / bbs / cit_src_AD08.lha / libmsg.c < prev    next >
C/C++ Source or Header  |  1998-06-06  |  12KB  |  451 lines

  1. /*
  2.  * *                            libmsg.c * * Common message handling
  3.  * functions for Citadel bulletin board system.
  4.  */
  5. /*
  6.  * *                            history * * 88Oct12 HAW  Generalize
  7.  * getMessage() * 87Feb11 HAW  Created.
  8.  */
  9. #include "ctdl.h"
  10. /*
  11.  * *                            contents * *    getMessage()            load
  12.  * message into RAM *   getMsgStr()             reads a string out of
  13.  * message.buf *        getMsgChar()            returns successive chars off
  14.  * disk *       startAt()               setup to read a message off disk *
  15.  * unGetMsgChar()               return a char to getMsgChar()
  16.  */
  17. extern FILE      *netLog;
  18.  
  19.  
  20. struct mBuf mFile1,
  21.           mFile2;
  22. MessageBuffer msgBuf,
  23.           tempMess;
  24. FILE     *msgfl,
  25.          *msgfl2;
  26. static int GMCCache;
  27. extern CONFIG cfg;
  28.  
  29. /*
  30.  * * getMessage() * * This function reads a message off disk into RAM.  The
  31.  * source of the message * is controlled by the Source parameter; if the
  32.  * source is ctdlmsg.sys, then * a previous call to setUp has specified the
  33.  * message. * * FromNet - this indicates if the message is coming from a
  34.  * network-generated * temporary file (TRUE) or from ctdlmsg.sys (FALSE).
  35.  * If the latter then this * function must find the start of message within
  36.  * the current sector.  Also, * the 'w' field of messages has different
  37.  * meanings depending on the source of * the message (messy, but useful). *
  38.  * * all - TRUE indicates the message text should be read in, FALSE
  39.  * indicates * reading should end when the 'M' field is encountered. * *
  40.  * ClearOthers - indicates all lists associated with msgBuf should be
  41.  * cleared * before the message is read in.
  42.  */
  43. char
  44. getMessage(int (*Source) (void), char FromNet, char all, char ClearOthers)
  45. {
  46.   int       c;
  47.   char      CC[CC_SIZE],
  48.            *d;
  49.   char      timedate[32];   /* decimal unsigned 32 bit number in text */
  50. /*
  51.  * clear msgBuf out
  52.  */
  53.   if (ClearOthers)
  54.     ZeroMsgBuffer(&msgBuf);
  55.   if (!FromNet)
  56.     {
  57.  /*
  58.   * only do this for messages from our own msgs
  59.   */
  60.       do
  61.     {
  62.       c = getMsgChar();
  63.  
  64.     }
  65.       while (c != 0xFF);    /*
  66.                  * find start of msg
  67.                  */
  68.       msgBuf.mbheadChar = mFile1.oldChar;    /*
  69.                          * record location
  70.                          */
  71.       msgBuf.mbheadSector = mFile1.oldSector;
  72.       getMsgStr(getMsgChar, msgBuf.mbId, NAMESIZE);
  73.     }
  74.   do
  75.     {
  76.       c = (*Source) ();
  77.       switch (c)
  78.     {
  79.       case 'A':
  80.         getMsgStr(Source, msgBuf.mbauth, sizeof msgBuf.mbauth);
  81.         break;
  82.       case 'D':
  83.         getMsgStr(Source, msgBuf.mbdate, NAMESIZE);
  84.         /**
  85.           dates are formatted as yyymmmdd or yymmmdd
  86.           The value of yyy can be 70 to 135 or 1970 to 2105 and
  87.           be valid...
  88.         **/
  89.         if (cfg.BoolFlags.tdebug) splitF(netLog, "Recieved D   field:%s\n", msgBuf.mbdate);
  90.         NormalizeDate((char *)&msgBuf.mbdate);  /* correct the date to standard format*/
  91.         if (cfg.BoolFlags.tdebug) splitF(netLog, "Normalized D field:%s\n", msgBuf.mbdate);
  92.         break;
  93.       case 'C':
  94.         getMsgStr(Source, msgBuf.mbtime, NAMESIZE);
  95.         if (cfg.BoolFlags.tdebug) splitF(netLog, "Recieved C field:%s\n", msgBuf.mbtime);
  96.         break;
  97.       case 'd':
  98.         /**
  99.           This field is a unix style date stamp.  It will be a 32 bit
  100.           unsigned integer set to the GMT of the message.  This means the
  101.           timezone adjustment must be made to the time/date for our time
  102.           prior to display.
  103.         **/
  104.         getMsgStr(Source, timedate, sizeof(timedate));
  105.         if (cfg.BoolFlags.tdebug) splitF(netLog, "Recieved d field:%s\n", timedate);
  106.         break;
  107.       case 'M':    /*
  108.              * just exit -- we'll read off disk
  109.              */
  110.         break;
  111.       case 'N':
  112.         getMsgStr(Source, msgBuf.mboname, NAMESIZE);
  113.         while ((d = strchr(msgBuf.mboname, '_')) != NULL)
  114.           *d = ' ';
  115.         break;
  116.       case 'O':
  117.         getMsgStr(Source, msgBuf.mborig, NAMESIZE);
  118.         break;
  119.       case 'R':
  120.         getMsgStr(Source, msgBuf.mbroom, NAMESIZE);
  121.         break;
  122.       case 'S':
  123.         getMsgStr(Source, msgBuf.mbsrcId, NAMESIZE);
  124.         break;
  125.       case 'T':
  126.         getMsgStr(Source, msgBuf.mbto, sizeof msgBuf.mbto);
  127.         break;
  128.       case 'Q':
  129.         getMsgStr(Source, msgBuf.mbaddr, sizeof msgBuf.mbaddr);
  130.         break;
  131.       case 'X':
  132.         getMsgStr(Source, msgBuf.mbdomain, NAMESIZE);
  133.         break;
  134.       case 'P':
  135.         getMsgStr(Source, msgBuf.mbOther, O_NET_PATH_SIZE);
  136.         break;
  137.       case 'W':
  138.         getMsgStr(Source, CC, CC_SIZE);
  139.         if (ClearOthers)
  140.           AddData(&msgBuf.mbCC, strdup(CC), NULL, FALSE);
  141.         break;
  142.       case 'w':
  143.         if (FromNet)
  144.           {
  145.         getMsgStr(Source, CC, CC_SIZE);
  146.         if (ClearOthers)
  147.           AddData(&msgBuf.mbOverride, strdup(CC), NULL, FALSE);
  148.  
  149.           }
  150.         else
  151.           {
  152.        /*
  153.         * now we can overload this -- 'w' is net only
  154.         */
  155.         getMsgStr(Source, msgBuf.mbreply, NAMESIZE);
  156.  
  157.           }
  158.         break;
  159.        /*
  160.         * yes, this is correct - we're overloading mbaddr.
  161.         */
  162.       case 't':
  163.         getMsgStr(Source, msgBuf.mbaddr, sizeof msgBuf.mbaddr);
  164.         break;
  165.       case -1:
  166.         return FALSE;
  167.       default:
  168.         if (isprint(c))
  169.           {
  170.        /*
  171.         * save foreign fields
  172.         */
  173.         msgBuf.mbtext[0] = c;
  174.         getMsgStr(Source, msgBuf.mbtext + 1, MAXTEXT - 5);
  175.         AddData(&msgBuf.mbForeign, strdup(msgBuf.mbtext), NULL, FALSE);
  176.         msgBuf.mbtext[0] = '\0';
  177.  
  178.           }
  179.         else if (c == 0xFF && !FromNet)
  180.           {
  181.        /*
  182.         * Damaged msgBase
  183.         */
  184.         unGetMsgChar(c);
  185.  
  186.           }
  187.         break;
  188.  
  189.     }
  190.  
  191.     }
  192.   while (c != 'M' && isprint(c));
  193.   if (c == 'M')
  194.     {
  195.       if (all)
  196.     getMsgStr(Source, msgBuf.mbtext, MAXTEXT);
  197.       return TRUE;
  198.  
  199.     }
  200.   return FALSE;
  201.  
  202. }
  203. /*
  204.  * * getMsgStr() * * This function reads a string from the given source.
  205.  */
  206. void
  207. getMsgStr(int (*Source) (void), char *dest, int lim)
  208. {
  209.   int       c;
  210.  
  211.   while ((c = (*Source) ()) && c != EOF)
  212.     {
  213.  /*
  214.   * read the complete string
  215.   */
  216.       if (lim)
  217.     {
  218.      /*
  219.       * if we have room then
  220.       */
  221.       lim--;
  222.       if (c == '\r')
  223.         c = '\n';
  224.       *dest++ = c;    /*
  225.              * copy char to buffer
  226.              */
  227.  
  228.     }
  229.  
  230.     }
  231.   if (!lim)
  232.     dest--;    /*
  233.          * Ensure not overwrite next door neighbor
  234.          */
  235.   *dest = '\0';        /*
  236.              * tie string off with null
  237.              */
  238.  
  239. }
  240. /*
  241.  * * getMsgChar() * * This function returns sequential chars from
  242.  * CtdlMsg.Sys.
  243.  */
  244. int
  245. getMsgChar()
  246. {
  247.   long      work;
  248.   int       toReturn;
  249.  
  250.   if (GMCCache)
  251.     {
  252.  /*
  253.   * someone did an unGetMsgChar() --return it
  254.   */
  255.       toReturn = GMCCache;
  256.       GMCCache = '\0';
  257.       return (toReturn & 0xFF);
  258.  
  259.     }
  260.   mFile1.oldChar = mFile1.thisChar;
  261.   mFile1.oldSector = mFile1.thisSector;
  262.   toReturn = mFile1.sectBuf[mFile1.thisChar];
  263.   toReturn &= 0xFF;    /*
  264.              * Only want the lower 8 bits
  265.              */
  266.   mFile1.thisChar = ++mFile1.thisChar % MSG_SECT_SIZE;
  267.   if (mFile1.thisChar == 0)
  268.     {
  269.  /*
  270.   * time to read next sector in:
  271.   */
  272.       mFile1.thisSector = ++mFile1.thisSector % cfg.maxMSector;
  273.       work = mFile1.thisSector;
  274.       work *= MSG_SECT_SIZE;
  275.       fseek(msgfl, work, 0);
  276.       if (fread(mFile1.sectBuf, MSG_SECT_SIZE, 1, msgfl) != 1)
  277.     {
  278.       crashout("?nextMsgChar-read fail");
  279.  
  280.     }
  281.       crypte(mFile1.sectBuf, MSG_SECT_SIZE, 0);
  282.  
  283.     }
  284.   return (toReturn);
  285.  
  286. }
  287. /*
  288.  * * startAt() * * This function sets the location to begin reading a
  289.  * message from. This is * usually only the sector, since byte offset within
  290.  * the sector is not * saved.
  291.  */
  292. void
  293. startAt(FILE * whichmsg, struct mBuf *mFile, SECTOR_ID sect, int byt)
  294. {
  295.   long      temp;
  296.  
  297.   GMCCache = '\0';    /*
  298.              * cache to unGetMsgChar() into
  299.              */
  300.   if (sect >= cfg.maxMSector)
  301.     {
  302.       printf("?startAt s=%u,b=%d", sect, byt);
  303.       return;    /*
  304.          * Don't crash anymore, just skip the msg
  305.          */
  306.  
  307.     }
  308.   mFile->thisChar = byt;
  309.   mFile->thisSector = sect;
  310.   temp = sect;
  311.   temp *= MSG_SECT_SIZE;
  312.   fseek(whichmsg, temp, 0);
  313.   if (fread(mFile->sectBuf, MSG_SECT_SIZE, 1, whichmsg) != 1)
  314.     {
  315.       crashout("?startAt read fail");
  316.  
  317.     }
  318.   crypte(mFile->sectBuf, MSG_SECT_SIZE, 0);
  319.  
  320. }
  321. /*
  322.  * * unGetMsgChar() * * This function returns (at most one) char to
  323.  * getMsgChar().
  324.  */
  325. void
  326. unGetMsgChar(char c)
  327. {
  328.   GMCCache = (int) c;
  329.  
  330. }
  331. /*
  332.  * * ZeroMsgBuffer() * * This function zeroes a message buffer.  This
  333.  * includes clearing lists out * legally, etc.
  334.  */
  335. void
  336. ZeroMsgBuffer(MessageBuffer * msg)
  337. {
  338.   memset(msg, 0, STATIC_MSG_SIZE);
  339.   KillList(&msg->mbCC);
  340.   KillList(&msg->mbOverride);
  341.   KillList(&msg->mbForeign);
  342.   msg->mbtext[0] = 0;
  343. }
  344. /*
  345.  * * InitMsgBase() * * This function opens the msg base(s), inits the msg
  346.  * buffers.
  347.  */
  348. void
  349. InitMsgBase()
  350. {
  351.   SYS_FILE  name;
  352.  
  353.   makeSysName(name, "ctdlmsg.sys", &cfg.msgArea);
  354.   openFile(name, &msgfl);
  355.   if (cfg.BoolFlags.mirror)
  356.     {
  357.       makeSysName(name, "ctdlmsg.sys", &cfg.msg2Area);
  358.       openFile(name, &msgfl2);
  359.  
  360.     }
  361.   InitBuffers();
  362.  
  363. }
  364. /*
  365.  * * InitBuffers() * * This function initializes the message buffers.
  366.  */
  367. void
  368. InitBuffers()
  369. {
  370.   static SListBase MsgBase =
  371.   {
  372.     NULL, ChkCC, NULL, free, strdup
  373.  
  374.   };
  375.  
  376.   copy_struct(MsgBase, msgBuf.mbCC);
  377.   copy_struct(MsgBase, msgBuf.mbOverride);
  378.   copy_struct(MsgBase, msgBuf.mbInternal);
  379.   copy_struct(MsgBase, msgBuf.mbForeign);
  380.   copy_struct(MsgBase, tempMess.mbOverride);
  381.   copy_struct(MsgBase, tempMess.mbCC);
  382.   copy_struct(MsgBase, tempMess.mbInternal);
  383.   copy_struct(MsgBase, tempMess.mbForeign);
  384.   msgBuf.mbtext = GetDynamic(MAXTEXT);
  385.   tempMess.mbtext = GetDynamic(MAXTEXT);
  386.  
  387. }
  388. /*
  389.  * * findMessage() * * This function will get all set up to do something
  390.  * with a message.
  391.  */
  392. char
  393. findMessage(SECTOR_ID loc, MSG_NUMBER id, char ClearOthers)
  394. {
  395.   MSG_NUMBER here;
  396.  
  397.   id &= S_MSG_MASK;
  398.   startAt(msgfl, &mFile1, loc, 0);
  399.   do
  400.     {
  401.       getMessage(getMsgChar, FALSE, FALSE, ClearOthers);
  402.       here = atol(msgBuf.mbId);
  403.     }
  404.   while (here != id && mFile1.thisSector == loc);
  405.   if (here != id)
  406.     mPrintf("Ooops, couldn't find %ld @ %d.\n ", id, loc);
  407.   return (char) ((here == id));
  408.  
  409. }
  410. /*
  411.  * * Preliminary comments & code for CC feature in C-86. * * Comments and
  412.  * notes. * * o Numerous requests for this feature tend to make it valuable.
  413.  * * * o Suggest we have a field which may have multiple instances in any
  414.  * message. *   This is the 'cc' field.  Suggest further that it be 2 *
  415.  * NAMESIZE bytes *   long in order to allow node designators. * * o
  416.  * Implementation: The getMessage() function should build a linked list *
  417.  * (possibly generic list: libarch.c) as it reads in a message of each *   CC
  418.  * recipient.  Will need to have a disposal function for this list as *
  419.  * each message is disposed of.  May take a little code massage to make *
  420.  * sure we hit all the high points. * * o Only available for Mail>. * o
  421.  * (Since getMessage handles all the forms of getting messages from any *
  422.  * source, this handles all the net forms, too.) * * o Code massage points
  423.  * not otherwise covered in this file: *   - Held Messages. *   - Interrupted
  424.  * Messages(!). *   - getMessage(). *   - putMessage() - how do we handle the
  425.  * analog to noteMessage()?  New *     parameter? * * o Network provisions *
  426.  *  - Net support not present for this type of message. *   - New field, net
  427.  * only: Recipient override.  Indicates who mail is to be *     given access
  428.  * to this message, may (easily) exclude recipient specified *     in the
  429.  * mbto[] field.  New field named mboverride[NAMESIZE * 2]. *   - Like mbCC,
  430.  * should be handled as list with multiple instances. *   - Check for mail
  431.  * should check this list instead of mbto iff mboverride *     is present. *
  432.  *  - mboverride fields will not contain node designators (initially). *
  433.  * mbCC fields will, where necessary. * * o Other comments and thoughts about
  434.  * design, etc. *   - Unlogged users should not have access. *   - List of CC
  435.  * users should be accessible to message writer. *   - Able to remove someone
  436.  * from list of CC users??? *   - Net designation.  Use STadel's '@'
  437.  * convention?  Seems logical. *   - NEED FORMAT FOR DISPLAY OF FINISHED &
  438.  * DELIVERED MESSAGE! *   - NETHACK3.MAN will need updating. *   - * * ALSO
  439.  * SEE CC.C.
  440.  */
  441. /*
  442.  * * ChkCC() * * This will see if the two records are identical.  This is
  443.  * used for list * searches.
  444.  */
  445. void     *
  446. ChkCC(char *d1, char *d2)
  447. {
  448.   return (strCmpU(d1, d2) == SAMESTRING) ? d1 : NULL;
  449.  
  450. }
  451.